package com.gadgets.busi.bm06.init;

import com.gadgets.busi.bm06.common.Bm06Constant;
import com.gadgets.busi.bm06.dto.TradeNodeTree;
import com.gadgets.busi.bm06.pojo.TradeNodeInfo;
import com.gadgets.busi.bm06.pojo.TradeNodeLink;
import com.gadgets.busi.bm06.repository.ITradeNodeInfoRepository;
import com.gadgets.busi.bm06.repository.ITradeNodeLinkRepository;
import com.gadgets.framework.common.util.CacheUtils;
import com.gadgets.framework.start.AbsCacheInitLoaderProcess;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;

/**
 * @author UncleXiu
 * @data 2022-02-27
 * @description
 */
@Component
public class Bm06StartProcess extends AbsCacheInitLoaderProcess {

    @Autowired
    private ITradeNodeInfoRepository tradeNodeInfoRepository;
    @Autowired
    private ITradeNodeLinkRepository tradeNodeLinkRepository;
    @Autowired
    private CacheUtils cacheUtils;

    public Bm06StartProcess() {
        super("6");
    }

    /**
     * 实际初始化执行方法
     */
    @Override
    public void initLoad() {
        logger.info("开始加载EU4贸易节点信息");
        List<TradeNodeInfo> nodeInfoList = tradeNodeInfoRepository.selectAllNodeInfo();
        logger.info("开始加载EU4贸易节点关联信息");
        List<TradeNodeLink> tradeNodeLinkList = tradeNodeLinkRepository.selectAllLinkInfo();
        logger.info("开始解析关联信息");
        HashMap<Long, List<TradeNodeLink>> linkCacheMap = new HashMap<>();
        for (TradeNodeLink tradeNodeLink : tradeNodeLinkList) {
            if(!linkCacheMap.containsKey(tradeNodeLink.getLinkNodeId())){
                linkCacheMap.put(tradeNodeLink.getLinkNodeId(), new ArrayList<>());
            }
            linkCacheMap.get(tradeNodeLink.getLinkNodeId()).add(tradeNodeLink);
        }
        logger.info("开始解析节点信息");
        HashMap<Long, TradeNodeInfo> nodeHashMap = new HashMap<>();
        List<TradeNodeInfo> endTradeNodeList = new ArrayList<>();
        for (TradeNodeInfo nodeInfo : nodeInfoList) {
            nodeHashMap.put(nodeInfo.getId(),nodeInfo);
            // 捕获贸易终点，用于后续的路径解析
            if(Bm06Constant.TRADE_NODE_TYPE.IN.equals(nodeInfo.getType())){
                endTradeNodeList.add(nodeInfo);
            }
        }
        logger.info("开始解析路径丛林");
        HashMap<Long, TradeNodeTree> treeHashMap = new HashMap<>();
        for (TradeNodeInfo nodeInfo : endTradeNodeList) {
            logger.debug("当前解析节点：{}",nodeInfo.getNodeName());
            buildTradeTree(linkCacheMap, nodeHashMap, treeHashMap, nodeInfo);
            logger.debug("完成节点解析：{}",nodeInfo.getNodeName());
        }
        logger.info("路径丛林解析完成");
        // 加入缓存
        cacheUtils.putDefualtCache(Bm06Constant.TRADE_INFO_CACHE_KEY.NODE_CACHE_KEY, nodeHashMap);
        cacheUtils.putDefualtCache(Bm06Constant.TRADE_INFO_CACHE_KEY.LINK_CACHE_KEY, linkCacheMap);
        cacheUtils.putDefualtCache(Bm06Constant.TRADE_INFO_CACHE_KEY.TRADE_TREE_CACHE, treeHashMap);
        logger.info("节点信息和关联信息已加入缓存");
    }

    protected TradeNodeTree buildTradeTree(HashMap<Long, List<TradeNodeLink>> linkCacheMap, HashMap<Long, TradeNodeInfo> nodeHashMap, HashMap<Long, TradeNodeTree> treeHashMap, TradeNodeInfo nodeInfo) {
        // 构建根节点
        TradeNodeTree tree = new TradeNodeTree(nodeInfo);
        List<TradeNodeLink> beforeNodeLinks = linkCacheMap.get(tree.getId());
        treeHashMap.put(tree.getId(), tree);
        if(null!=beforeNodeLinks) {
            for (TradeNodeLink beforeNodeLink : beforeNodeLinks) {
                // 获取输出节点
                if(treeHashMap.containsKey(beforeNodeLink.getNodeId())){
                    // 如果当前节点的树已经存在，则直接使用现有的树
                    tree.addTreeSon(treeHashMap.get(beforeNodeLink.getNodeId()));
                }else {
                    // 如果当前节点的树不存在，则创建一棵树
                    TradeNodeInfo befreNode = nodeHashMap.get(beforeNodeLink.getNodeId());
                    tree.addTreeSon(buildTradeTree(linkCacheMap, nodeHashMap, treeHashMap, befreNode));
                }
            }
        }
        return tree;
    }

}
